"""
Schemas for the two strand 454 sequencing

>>> fname = atlas.testdata('test-database.hdf', verify=False)
>>> db = hdf.hdf_open(fname, mode='w', title='Test database')
>>> table = hdf.create_table( db=db, name='foo', schema=Mod454Schema, clobber=True )
>>> db.close()

$Rev: 56 $ 
$Author: ialbert $ 
$Date: 2008-01-01 07:33:58 -0500 (Tue, 01 Jan 2008) $
"""
import numpy
import atlas
from atlas import hdf, commify
from tables import IsDescription, IntCol, FloatCol
from math import log, exp

class Mod454Schema( IsDescription ):
    """
    Schema for the 454 sequencer

    Stores a triplet of float values for each index.
    """
    ix = IntCol  ( pos=1 )  # index
    wx = FloatCol( pos=2 )  # values on the W (forward) strand
    cx = FloatCol( pos=3 )  # value on the C (reverse) strand
    ax = FloatCol( pos=4 )  # weighted value on the combined W + C strands

def get(table, start, end):
    """
    Returns a row of numpy arrays for the given range of the index
    """
    out = []        
    lo, hi = hdf.index_search(table=table, args=(start, end), colattr='ix')
    for attr in ('ix', 'wx', 'cx', 'ax'):
        col = getattr(table.cols, attr)[lo:hi]
        out.append( col )
    return out

def hdf_query(db, name, param, autosize=False ):
    """
    Schema specific hdf query. 
    Note that returns data as columns not rows.
    """
    if not hdf.has_node(db=db, name=name):
        atlas.warn( 'missing label %s' % name )
        return [], [], [], []
    data  = hdf.GroupData( db=db, name=name)
    istart, iend = data.get_indices(label=param.chrom, start=param.start, stop=param.end)
    table = data.get_table(label=param.chrom)
    if autosize:
        # attempts to reduce the number of points
        size = len( table.cols.ix[istart:iend] )
        step = max( [1, size/1200] )
    else:
        step = 1

    ix = table.cols.ix[istart:iend:step].tolist()
    wx = table.cols.wx[istart:iend:step].tolist()
    cx = table.cols.cx[istart:iend:step].tolist()
    ax = table.cols.ax[istart:iend:step].tolist()
    return ix, wx, cx, ax

def parser( row ):
    """
    Default parser. Takes as input a dictionary keyed by the data header,
    returns a tuple that fits the schema.

    A parser *MUST* return items in the same order as they are listed pos 
    argument of each field of the schema
    """
    ix = int( row['index'] )
    wx = float( row['forward'] )
    cx = float( row['reverse'] )
    ax = wx + cx
    return ix, wx, cx, ax

def test(verbose=0):
    """
    Main testrunnner
    """
    import doctest
    doctest.testmod( optionflags=doctest.ELLIPSIS + doctest.NORMALIZE_WHITESPACE, verbose=verbose )

if __name__ == '__main__':
    test(verbose=0)
